package com.lemon.cloud.minio.http;

import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.lemon.cloud.minio.service.OssTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author HuangDS
 */
@Validated
@RestController
@RequestMapping({"${oss.http.prefix:}/oss"})
public class OssEndpoint {
    private final OssTemplate ossTemplate;

    @PostMapping({"/bucket/{bucketName}"})
    public Bucket createBucket(@PathVariable("bucketName") @NotBlank String bucketName) {
        this.ossTemplate.createBucket(bucketName);
        return this.ossTemplate.getBucket(bucketName).get();
    }

    @GetMapping({"/bucket"})
    public List<Bucket> getBuckets() {
        return this.ossTemplate.getAllBuckets();
    }

    @GetMapping({"/bucket/{bucketName}"})
    public Bucket getBucket(@PathVariable("bucketName") @NotBlank String bucketName) {
        return this.ossTemplate.getBucket(bucketName).orElseThrow(() -> new IllegalArgumentException("Bucket Name not found!"));
    }

    @DeleteMapping({"/bucket/{bucketName}"})
    @ResponseStatus(HttpStatus.ACCEPTED)
    public void deleteBucket(@PathVariable("bucketName") @NotBlank String bucketName) {
        this.ossTemplate.removeBucket(bucketName);
    }


    @PostMapping({"/object/{bucketName}/{objectName}"})
    public S3ObjectSummary createObject(@RequestBody @NotNull MultipartFile object,
                                        @PathVariable("bucketName") @NotBlank String bucketName,
                                        @PathVariable("objectName") @NotBlank String objectName) throws IOException {
        try {
            InputStream inputStream = object.getInputStream();
            S3ObjectSummary s3ObjectSummary;
            try {
                this.ossTemplate.putObject(bucketName, objectName, inputStream, object.getSize(), object.getContentType());
                S3Object objectInfo = this.ossTemplate.getObjectInfo(bucketName, objectName);
                ObjectMetadata objectMetadata = objectInfo.getObjectMetadata();
                S3ObjectSummary objectSummary = new S3ObjectSummary();
                objectSummary.setKey(objectInfo.getKey());
                objectSummary.setBucketName(bucketName);
                objectSummary.setETag(objectMetadata.getETag());
                objectSummary.setLastModified(objectMetadata.getLastModified());
                objectSummary.setSize(objectMetadata.getContentLength());
                s3ObjectSummary = objectSummary;
            } finally {
                if (Collections.singletonList(inputStream).get(0) != null) {
                    inputStream.close();
                }

            }
            return s3ObjectSummary;
        } catch (Throwable throwable) {
            throw throwable;
        }
    }

    @GetMapping({"/object/{bucketName}/{objectName}"})
    public List<S3ObjectSummary> filterObject(@PathVariable("bucketName") @NotBlank String bucketName,
                                              @PathVariable("objectName") @NotBlank String objectName) {
        return this.ossTemplate.getAllObjectsByPrefix(bucketName, objectName);
    }

    @GetMapping({"/object/{bucketName}/{objectName}/{expires}"})
    public Map<String, Object> getObjectUrl(@PathVariable("bucketName") @NotBlank String bucketName,
                                            @PathVariable("objectName") @NotBlank String objectName,
                                            @PathVariable("expires") @NotNull Integer expires) {
        Map<String, Object> responseBody = new HashMap<>(8);
        responseBody.put("bucket", bucketName);
        responseBody.put("object", objectName);
        responseBody.put("url", this.ossTemplate.getObjectURL(bucketName, objectName, expires));
        responseBody.put("expires", expires);
        return responseBody;
    }

    @GetMapping({"/object/put/{bucketName}/{objectName}/{expires}"})
    public Map<String, Object> getPutObjectUrl(@PathVariable("bucketName") @NotBlank String bucketName,
                                               @PathVariable("objectName") @NotBlank String objectName,
                                               @PathVariable("expires") @NotNull Integer expires) {
        Map<String, Object> responseBody = new HashMap<>(8);
        responseBody.put("bucket", bucketName);
        responseBody.put("object", objectName);
        responseBody.put("url", this.ossTemplate.getPutObjectURL(bucketName, objectName, expires));
        responseBody.put("expires", expires);
        return responseBody;
    }

    @ResponseStatus(HttpStatus.ACCEPTED)
    @DeleteMapping({"/object/{bucketName}/{objectName}/"})
    public void deleteObject(@PathVariable("bucketName") @NotBlank String bucketName,
                             @PathVariable("objectName") @NotBlank String objectName) {
        this.ossTemplate.removeObject(bucketName, objectName);
    }

    public OssEndpoint(final OssTemplate ossTemplate) {
        this.ossTemplate = ossTemplate;
    }
}
